package net.chrisrichardson.ec2deployer.core

import org.apache.commons.logging.*;

public class Ssh implements CloudCommandExecutor {

    Log logger = LogFactory.getLog(getClass())
    ProcessMonitor defaultProcessMonitor

    String sshOpts = "-o BatchMode=yes -o StrictHostKeyChecking=no"
    private AWSProperties awsProperties

    def Ssh(AWSProperties awsProperties) {
        this.awsProperties = awsProperties
    }


    // todo - somehow check that permissions on id_rsa-gsg-keypair are ok

    void checkExitValue(int exitValue, String cmd) {
        if (exitValue != 0) throw new ProcessExecutionException(cmd, exitValue)
    }

    public void ssh(String publicDnsName, String command, String input = null, ProcessMonitor processMonitor = null, String options = "") {
        String readableCommand = "ssh on ${publicDnsName}:  $command"
        logger.debug(readableCommand)
        if (!processMonitor) processMonitor = defaultProcessMonitor
        processMonitor?.noteCommand(readableCommand)
        int exitValue = new ProcessExecutor().execute("${awsProperties.sshDir}/ssh $sshOpts -i ${awsProperties.keyPairFile} $options root@$publicDnsName $command", input, processMonitor)
        checkExitValue(exitValue, readableCommand);
    }

    public void scpUp(String publicDnsName, String fromFile, String toFile) {
        String readableCommand = "scp to ${publicDnsName}: $fromFile -> $toFile"
        logger.debug(readableCommand)
        defaultProcessMonitor?.noteCommand(readableCommand)
        int exitValue = new ProcessExecutor().execute("${awsProperties.sshDir}/scp $sshOpts -i ${awsProperties.keyPairFile} $fromFile root@$publicDnsName:$toFile", null, defaultProcessMonitor)
        println exitValue
        checkExitValue(exitValue, readableCommand)
    }

    public void scpDown(String publicDnsName, String fromFile, String toFile) {
        String readableCommand = "scp from ${publicDnsName}: $fromFile -> $toFile"
        logger.debug(readableCommand)
        defaultProcessMonitor?.noteCommand(readableCommand)
        int exitValue = new ProcessExecutor().execute("${awsProperties.sshDir}/scp $sshOpts -i ${awsProperties.keyPairFile} root@$publicDnsName:$fromFile $toFile", null, defaultProcessMonitor)
        checkExitValue(exitValue, readableCommand)
    }

    void waitUntilSshAvailable(String publicDnsName) {
        logger.debug "waiting for ssh: " + publicDnsName

        for (int i: 0..10) {
            if (isSshAvailable(publicDnsName))
                break;
            Thread.sleep 5 * 1000
        }
    }

    boolean isSshAvailable(String publicDnsName) {
        Socket s = null
        try {
            s = new Socket();
            s.connect(new InetSocketAddress(publicDnsName, 22), 5 * 1000);
            logger.debug "Connected"
            return true;
        } catch (IOException e) {
            logger.debug("connection failed:", e)
            return false;
        } finally {
            try {
                if (s) s.close();
            } catch (IOException e) {
            }
        }
    }

}
